// src/services/examples/indicator-calculator.ts
import { MarketDataService, KlineBar } from '../services/market-data.service';
import { IndicatorsService } from '../services/indicators.service';
import { KlineUtilsService } from '../services/kline-utils.service';
import { IndicatorLoggerService, KlineDataItem } from '../services/indicator-logger.service';
import { Config } from '../utils/config.service';

// 导出配置类型定义
export { Config };

/**
 * 指标计算器类
 * 负责协调各服务，执行指标计算和日志记录
 */
export class IndicatorCalculator {
  private marketDataService: MarketDataService;
  private indicatorsService: IndicatorsService;
  private klineUtils: KlineUtilsService;

  constructor(private config: Config) {
    // 初始化服务
    const apiConfig = config.global.api || {};

    this.marketDataService = new MarketDataService(
      apiConfig.baseUrl,
      {
        proxy: apiConfig.proxy || undefined,
        timeout: apiConfig.timeout || 30000
      }
    );

    this.indicatorsService = new IndicatorsService();
    this.klineUtils = new KlineUtilsService();
  }

  /**
   * 启动指标计算
   */
  async start(): Promise<void> {
    console.log('正在初始化服务...');

    // 测试API连接
    const connectionTest = await this.marketDataService.testConnection();
    if (!connectionTest.success) {
      throw new Error(`连接测试失败: ${connectionTest.message}`);
    }
    console.log('API连接测试成功!');

    // 处理每个交易对的指标计算
    for (const instrument of this.config.instruments) {
      await this.processInstrument(instrument);
    }
  }

  /**
   * 处理单个交易对的指标计算
   */
  private async processInstrument(instrument: Config['instruments'][0]): Promise<void> {
    console.log(`\n===== 处理交易对: ${instrument.instId} =====`);

    // 按周期分组所有指标配置，避免重复获取K线数据
    const periodGroups: Map<string, Array<{ type: string, config: any }>> = new Map();

    // 遍历所有指标配置，按周期分组
    for (const indicator of instrument.indicators) {
      for (const config of indicator.configs) {
        const barStr = config.bar;

        // 获取或创建该周期的指标组
        if (!periodGroups.has(barStr)) {
          periodGroups.set(barStr, []);
        }

        // 将指标添加到对应周期组
        periodGroups.get(barStr)?.push({
          type: indicator.type,
          config
        });
      }
    }

    // 处理每个周期组
    for (const [barStr, indicators] of periodGroups.entries()) {
      console.log(`\n-- 处理 ${barStr} 周期的指标数据 --`);

      try {
        // 获取该周期的K线数据（只获取一次）
        const klineData = await this.marketDataService.fetchKlineData(
          instrument.instId,
          barStr,
          this.config.global.dataLimit
        );
        console.log(`获取到 ${klineData.length} 条 ${barStr} 周期K线数据`);

        // 保存最新的100条K线数据到txt文件
        IndicatorLoggerService.saveKlineDataToTxt(
          klineData as KlineDataItem[],
          instrument.instId,
          barStr,
          100,
          this.config.global.logDir
        );

        // 获取价格映射（所有指标共用）
        const priceMap = this.klineUtils.createPriceMap(klineData);

        // 处理该周期的所有指标
        for (const { type: indicatorType, config } of indicators) {
          console.log(`计算 ${barStr} 周期的 ${indicatorType} 指标...`);

          // 计算指标
          const indicatorResults = this.indicatorsService.calculateIndicator(
            klineData,
            indicatorType,
            config
          );
          console.log(`计算出 ${indicatorResults.length} 个 ${indicatorType} 指标值`);

          // 分析指标结果，为每个数据点添加信号，并输出最新的分析结果
          const enrichedResults = this.outputIndicatorAnalysis(indicatorType, indicatorResults);

          // 创建指标日志记录器
          const logger = new IndicatorLoggerService(
            instrument.instId,
            barStr,
            indicatorType,
            { logDir: this.config.global.logDir }
          );

          // 获取最新数据点的信号
          const latestResult = enrichedResults[enrichedResults.length - 1];

          // 使用包含所有数据点信号的方法初始化日志
          logger.initializeIndicatorLogWithSignal(enrichedResults, priceMap, latestResult.signal);

          console.log(`${indicatorType} 指标日志已保存，最新信号: ${latestResult.signal}`);
        }
      } catch (error: any) {
        console.error(`处理 ${barStr} 周期数据时出错:`, error.message);
      }
    }

    // 如果启用了实时更新，可在这里设置WebSocket
    if (this.config.global.enableRealtime) {
      console.log(`\n已启用实时更新，为 ${instrument.instId} 设置WebSocket...`);
      // TODO: 实现WebSocket实时更新逻辑
    }
  }

  /**
   * 处理单个指标配置（保留旧方法作为参考）
   * @deprecated 请使用新的按周期分组处理方法
   */
  private async _processIndicatorConfig(
    instId: string,
    indicatorType: string,
    config: any
  ): Promise<void> {
    // 这个方法已经被新的按周期分组处理方法替代
    // 保留作为参考，未来可以删除
  }

  /**
   * 分析指标结果，为每个数据点添加信号，并输出最新的分析结果
   * @param indicatorType 指标类型
   * @param results 指标结果数组
   * @returns 添加了信号属性的指标结果数组
   */
  private outputIndicatorAnalysis(
    indicatorType: string,
    results: any[]
  ): any[] {
    if (results.length === 0) return [];

    // 为每个数据点计算信号
    const enrichedResults = results.map(result => {
      // 分析当前数据点
      const analysis = this.indicatorsService.analyzeIndicator(indicatorType, result);

      // 创建新对象，添加信号字段
      return {
        ...result,
        signal: analysis.status
      };
    });

    // 获取最新的结果和分析用于控制台输出
    const latestResult = enrichedResults[enrichedResults.length - 1];
    const latestAnalysis = this.indicatorsService.analyzeIndicator(indicatorType, latestResult);

    // 输出分析结果到控制台
    console.log('\n指标分析:');
    console.log(`状态: ${latestAnalysis.status}`);
    console.log(latestAnalysis.message);

    // 输出具体值
    console.log('\n具体数值:');
    Object.entries(latestResult.values || latestResult).forEach(([key, value]) => {
      if (key !== 'timestamp' && key !== 'type' && key !== 'signal') {
        console.log(`${key}: ${Number(value).toFixed(2)}`);
      }
    });

    // 返回带有信号的结果数组
    return enrichedResults;
  }
} 